#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <unistd.h>
#define ARRAY_SIZE 8

// 读写锁
pthread_rwlock_t rwlock;

//全局变量
int num = 0;

void * fun_read(void * arg){
    int index = (int)(long)arg;
    while (1){
        // 加读锁
        pthread_rwlock_rdlock(&rwlock);
        printf("thread %d read num=%d\n",index,num);
        // 解锁
        pthread_rwlock_unlock(&rwlock);
        //随机睡眠 1-3 秒
        sleep(random() % 3 +1);
    }
    return NULL;
}

void * fun_write(void * arg){

    int index = (int)(long)arg;
    while (1){
        // 加写锁
        pthread_rwlock_wrlock(&rwlock);
        num ++;
        printf("thread %d write num=%d\n",index,num);
        // 解锁
        pthread_rwlock_unlock(&rwlock);
        //随机睡眠 1-3 秒
        sleep(random() % 3 +1);
    }

    return NULL;
}

/**
 * 读写锁
 *      特点：
 *          如果有其他线程读数据，则允许其他线程执行读操作，但是不允许写操作
 *          如果有其他线程写数据，则其他线程不允许读写操作
 *      规则：
 *          如果某线程申请了读锁，其他线程可以再次申请读锁，但是不可以申请写锁
 *          如果某线程申请了写锁，其他线程既不可以申请读锁，也不可以申请写锁
 * @return
 */

int main(){
    pthread_t tids[ARRAY_SIZE];
    int ret = -1;

    // 设置随机种子
    srandom(getpid());

    //初始化读写锁
    ret = pthread_rwlock_init(&rwlock,NULL);
    // 创建 5个读线程，3个写线程
    for (int i = 0; i < ARRAY_SIZE; ++i) {
        if(i < 5){
            pthread_create(&tids[i],NULL,fun_read,(void *)(long)i);
        }
        else{
            pthread_create(&tids[i],NULL,fun_write,(void *)(long)i);
        }
    }

    //回收资源
    for (int i = 0; i < ARRAY_SIZE; ++i) {
        pthread_join(tids[i],NULL);
    }
    // 销毁读写锁
    pthread_rwlock_destroy(&rwlock);
    printf("main exit...\n");
    return 0;
}
